import 'package:flutter/material.dart';
import 'dart:async';

class MDTypewriterWidgetSpan extends StatefulWidget {
  final InlineSpan inlineSpan;
  final Duration duration;
  final bool needType;
  final Function onComplete;
  final Function onLineBreak;

  const MDTypewriterWidgetSpan({
    Key? key,
    required this.inlineSpan,
    this.needType = true,
    required this.onComplete,
    required this.onLineBreak,
    this.duration = const Duration(milliseconds: 100),
  }) : super(key: key);

  @override
  _MDTypewriterWidgetSpanState createState() => _MDTypewriterWidgetSpanState();
}

class _MDTypewriterWidgetSpanState extends State<MDTypewriterWidgetSpan> with AutomaticKeepAliveClientMixin{
  String _displayText = '';
  int _currentIndex = 0;
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    if (widget.needType) {
      _startTypewriter();
    } else {
      setState(() {
        _displayText = _getTextFromInlineSpan(widget.inlineSpan);
      });
    }
  }

  void _startTypewriter() {
    _timer = Timer.periodic(widget.duration, (timer) {
      final text = _getTextFromInlineSpan(widget.inlineSpan);
      if (_currentIndex < text.length) {
        setState(() {
          _displayText += text[_currentIndex];
          _currentIndex++;
          _checkLineBreak(); // 检查是否换行
        });
      } else {
        widget.onComplete();
        timer.cancel();
      }
    });
  }

  void _checkLineBreak() {
    final textPainter = TextPainter(
      text: TextSpan(text: _displayText, style: DefaultTextStyle.of(context).style),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout(maxWidth: MediaQuery.of(context).size.width);

    final textHeight = textPainter.size.height;
    if (textHeight > DefaultTextStyle.of(context).style.fontSize!) {
      widget.onLineBreak(); // 触发换行回调
    }
  }

  String _getTextFromInlineSpan(InlineSpan inlineSpan) {
    String text = '';
    void visitInlineSpan(InlineSpan span) {
        if (span is TextSpan) {
            text += span.text ?? '';
        }
    }
    visitInlineSpan(inlineSpan);
    return text;
  }

  @override
  void dispose() {
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Text.rich(
      TextSpan(
        style: DefaultTextStyle.of(context).style,
        children: [
          TextSpan(text: _displayText),
        ],
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}